package com.hemerasolutions.v2trainer.model.training;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;

import com.hemerasolutions.v2trainer.model.base.BaseModel;
import com.hemerasolutions.v2trainer.model.exercise.Exercise;
import com.hemerasolutions.v2trainer.model.exerciseGroup.ExerciseGroup;
import com.hemerasolutions.v2trainer.model.interfaces.BaseModelInterface;
import com.hemerasolutions.v2trainer.model.modality.Modality;
import com.hemerasolutions.v2trainer.model.step.Step;
import com.hemerasolutions.v2trainer.model.training.statistic.StatisticUnit;
import com.hemerasolutions.v2trainer.model.training.statistic.TrainingStatistic;

@Entity
public class TrainingStep extends BaseModel implements BaseModelInterface  {

	private static final long serialVersionUID = 1L;

    @Column(length = 1)
	private int level;
	
    @ManyToOne
    private Training training;
    
    @OneToOne(cascade=CascadeType.ALL,orphanRemoval=true)
	private Step rootStep;
    
    @ManyToMany(fetch=FetchType.EAGER)
    private List<StatisticUnit> statisticUnits;
    
    @OneToMany(fetch=FetchType.LAZY,cascade=CascadeType.ALL,orphanRemoval=true)
    private List<TrainingStatistic> trainingStatistics;
 
    @OneToOne(fetch=FetchType.LAZY,cascade=CascadeType.ALL,orphanRemoval=true)
    private TrainingStatistic rootStatistic;
     
    
    public static final int LEVEL_GENERAL 		= 0;
    public static final int LEVEL_SEDENTARY 	= 1;
    public static final int LEVEL_BEGINNER		= 2;
    public static final int LEVEL_MODERATELY 	= 3;
    public static final int LEVEL_TRAINED		= 4; 
    public static final int LEVEL_HIGHLY		= 5;

    
    public TrainingStep(TrainingStep other, Training training){
    	this();

    	this.level = other.level;
    	this.training = training;
    	this.rootStep = new Step(this,other.rootStep,null);
    	this.rootStatistic = new TrainingStatistic(this,other.rootStatistic); 

    	this.statisticUnits.addAll(other.statisticUnits);

    	for(TrainingStatistic ts:other.trainingStatistics){
    		this.trainingStatistics.add(new TrainingStatistic(this,ts));
    	}
    	
    }
    
    public TrainingStep() {
		super();
		this.rootStep = new Step(this,Step.ROOT_STEP,null);
		this.rootStatistic = new TrainingStatistic(this,TrainingStatistic.ROOT_STATISTIC);
		this.statisticUnits = new ArrayList<StatisticUnit>();
	}

    public String getLevelName(){
    	switch (this.level) {
		case LEVEL_GENERAL:
			return 	"LEVEL_GENERAL";
		case LEVEL_SEDENTARY:
			return 	"LEVEL_SEDENTARY";
		case LEVEL_BEGINNER:
			return 	"LEVEL_BEGINNER";
		case LEVEL_MODERATELY:
			return 	"LEVEL_MODERATELY";
		case LEVEL_TRAINED:
			return 	"LEVEL_TRAINED";
		case LEVEL_HIGHLY:
			return 	"LEVEL_HIGHLY";
		default:
			return 	"LEVEL_GENERAL";
		}
    }


	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public int getLevel() {
		return level;
	}

	public void setLevel(int level) {
		this.level = level;
	}

	public Training getTraining() {
		return training;
	}

	public void setTraining(Training training) {
		this.training = training;
	}

    public Step getRootStep() {
		return rootStep;
	}

	public void setRootStep(Step rootStep) {
		this.rootStep = rootStep;
	}

	public boolean isEmpty(){
    	return this.rootStep.getSteps().isEmpty();
    }

	public List<StatisticUnit> getStatisticUnits() {
		return statisticUnits;
	}

	public void setStatisticUnits(List<StatisticUnit> statisticUnits) {
		this.statisticUnits = statisticUnits;
	}
	

	public List<TrainingStatistic> getTrainingStatistics() {
		return trainingStatistics;
	}

	public void setTrainingStatistics(List<TrainingStatistic> trainingStatistics) {
		this.trainingStatistics = trainingStatistics;
	}

	public TrainingStatistic getRootStatistic() {
		return rootStatistic;
	}

	public void setRootStatistic(TrainingStatistic rootStatistic) {
		this.rootStatistic = rootStatistic;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		result = prime * result + level;
		result = prime * result
				+ ((training == null) ? 0 : training.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		TrainingStep other = (TrainingStep) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		if (level != other.level)
			return false;
		if (training == null) {
			if (other.training != null)
				return false;
		} else if (!training.equals(other.training))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "TrainingStep [id=" + id + ", level=" + level + ", training="
				+ training + "]";
	}

	public void addArbritaryUnit(StatisticUnit unit) {
		
		if(!this.statisticUnits.contains(unit)){
			this.statisticUnits.add(unit);
		}
	}
    
	public void removeArbritaryUnit(StatisticUnit unit) {
		
		if(this.statisticUnits.contains(unit)){
			this.statisticUnits.remove(unit);
		}
	}

	public List<Modality> collectModalitys() {
		return this.rootStep.collectModalitys();
	}

	public List<Training> collectTainings() {
		return this.rootStep.collectTrainings();
	}

	public List<ExerciseGroup> collectExerciseGroups() {
		return this.rootStep.collectExerciseGroups();
	}

	public List<Exercise> collectExercises() {
		return this.rootStep.collectExercises();
	}
    	
	
	

	
}
